<?php

namespace App\JsonRpc;

use App\Exception\ServiceException;
use App\Model\CouponModel;
use App\Model\UserCollectionModel;
use App\Model\UserCouponModel;
use App\Util\Common;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\RpcServer\Annotation\RpcService;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Hyperf\Context\Context;
use Hyperf\Contract\ConfigInterface;
use App\JsonRpc\MerchantServiceInterface;
use App\JsonRpc\ManagerServiceInterface;
use function Hyperf\Support\env;

#[RpcService(name: "CouponService", protocol: "jsonrpc-http", server: "jsonrpc-http", publishTo:"nacos")]
class CouponService implements CouponServiceInterface
{
    /**
     * @var LoggerInterface
     */
    protected LoggerInterface $logger;

    /**
     * @var 用户登录数据
     */
    protected $authData;

    /**
     * @var $util 工具类
     */
    protected $util;

    /**
     * @var $config 配置对象
     */
    protected $config;

    #[Inject]
    protected MerchantServiceInterface $merchantService;

    #[Inject]
    protected ManagerServiceInterface $managerService;

    /**
     * @var $http_code_config http状态码配置
     */
    protected $http_code;

    public function __construct(ContainerInterface $container)
    {
        $this->logger = $container->get(StdoutLoggerInterface::class);
        $this->authData = Context::get("user_info");
        $this->util = new Common();
        $this->config = $container->get(ConfigInterface::class);
        $this->http_code = $this->config->get("http_code");
    }

    /**
     * 新增优惠券
     * @param array $data 请求数据
     * @return bool|int 返回结果
     */
    public function create(array $data): bool|int
    {
        // 获取用户权限(不是平台管理员，不能发布平台券)
        if(trim($this->authData["payload"]["platform"]) != "platform"){
            if(intval($data["type"]) == 2){
                throw new ServiceException($this->util->make_message(1,"权限不足，不能发布平台优惠券"),$this->http_code["forbidden"]);
            }
        }
        // 验证条件 类型 0：商家通用  1：特定专属  2：平台
        if(intval($data["type"]) == 2){
            // 平台券商户ID为0
            $data["merchant_id"] = 0;
        }
        // 验证减免条件 优惠类型 0：满减 1：立减  2：折扣
        if(intval($data["discount_type"]) == 0){
            if(floatval($data["conditional_amount"]) < floatval($data["discount_amount"])){
                throw new ServiceException($this->util->make_message(1,"满减券减免金额不能大于条件金额"),$this->http_code["forbidden"]);
            }
        }
        // 折扣券条件金额为0， 并且减免金额为0-1的小数
        if(intval($data["discount_type"]) == 2){
            if(floatval($data["discount_amount"]) <= 0 || floatval($data["discount_amount"]) > 1){
                throw new ServiceException($this->util->make_message(1,"折扣券减免金额比例超出范围"),$this->http_code["forbidden"]);
            }
            $data["conditional_amount"] = 0;
        }
        // 处理标题
        $data["title"] = '';
        switch (intval($data["discount_type"])){
            case 0:
                $data["title"] = "满".floatval($data["conditional_amount"])."元减".floatval($data["discount_amount"])."元";
                break;
            case 1:
                $data["title"] = "立减".floatval($data["discount_amount"])."元";
                break;
            case 2:
                $data["title"] = round(floatval($data["discount_amount"]) * 10,1)."折券";
                break;
            default:
                break;
        }
        // 验证有效期 有效期类型 0：长期 1：有限时间
        if(intval($data["period_validity"]) == 0){
            $data["expiration_date"] = 0;
        }
        // 验证用户权限
        if((int)$data["type"] == 0 || (int)$data["type"] == 1){
            // 获取商户信息
            $merchantInfo = $this->merchantService->info([["user_id",'=',$this->authData["id"]]],['*']);
            if(is_null($merchantInfo)){
                throw new ServiceException($this->util->make_message(1,"请先申请入驻商户"),$this->http_code["no_found"]);
            }
            if($merchantInfo["status"] == 0){
                throw new ServiceException($this->util->make_message(1,"商户已被禁用，请联系平台管理员"),$this->http_code["forbidden"]);
            }
            $data["merchant_id"] = $merchantInfo["id"];
        }
        $data["id"] = $this->generate_id();
        $data["created_at"] = date("Y-m-d H:i:s",time());
        $data["updated_at"] = date("Y-m-d H:i:s",time());
        // 保存数据
        return CouponModel::query()->insert($data);
    }

    /**
     * 修改优惠券
     * @param string $id 优惠券ID
     * @param array $data 请求数据
     * @return bool|int 返回结果
     */
    public function update(string $id, array $data): bool|int
    {
        // 获取用户权限(不是平台管理员，不能发布平台券)
        if(trim($this->authData["payload"]["platform"]) != "platform"){
            if(intval($data["type"]) == 2){
                throw new ServiceException($this->util->make_message(1,"权限不足，不能发布平台优惠券"),$this->http_code["forbidden"]);
            }
        }
        // 验证条件 类型 0：商家通用  1：特定专属  2：平台
        if(intval($data["type"]) == 2){
            // 平台券商户ID为0
            $data["merchant_id"] = '';
        }
        // 验证减免条件 优惠类型 0：满减 1：立减  2：折扣
        if(intval($data["discount_type"]) == 0){
            if(floatval($data["conditional_amount"]) < floatval($data["discount_amount"])){
                throw new ServiceException($this->util->make_message(1,"满减券减免金额不能大于条件金额"),$this->http_code["forbidden"]);
            }
        }
        // 折扣券条件金额为0， 并且减免金额为0-1的小数
        if(intval($data["discount_type"]) == 2){
            if(floatval($data["discount_amount"]) <= 0 || floatval($data["discount_amount"]) > 1){
                throw new ServiceException($this->util->make_message(1,"折扣券减免金额比例超出范围"),$this->http_code["forbidden"]);
            }
            $data["conditional_amount"] = 0;
        }
        // 处理标题
        $data["title"] = '';
        switch (intval($data["discount_type"])){
            case 0:
                $data["title"] = "满".floatval($data["conditional_amount"])."元减".floatval($data["discount_amount"])."元";
                break;
            case 1:
                $data["title"] = "立减".floatval($data["discount_amount"])."元";
                break;
            case 2:
                $data["title"] = round(floatval($data["discount_amount"]) * 10,1)."折券";
                break;
            default:
                break;
        }
        // 验证有效期 有效期类型 0：长期 1：有限时间
        if(intval($data["period_validity"]) == 0){
            $data["expiration_date"] = 0;
        }
        // 获取优惠券信息
        $coupon = CouponModel::query()->where("id",'=',$id)->first();
        if(is_null($coupon)){
            throw new ServiceException($this->util->make_message(1,"优惠券信息不存在"),$this->http_code["no_found"]);
        }
        // 验证用户权限
        if((int)$data["type"] == 0 || (int)$data["type"] == 1){
            // 获取商户信息
            $merchantInfo = $this->merchantService->info([["user_id",'=',$this->authData["id"]]],['*']);
            if(is_null($merchantInfo)){
                throw new ServiceException($this->util->make_message(1,"请先申请入驻商户"),$this->http_code["no_found"]);
            }
            if($merchantInfo["status"] == 0){
                throw new ServiceException($this->util->make_message(1,"商户已被禁用，请联系平台管理员"),$this->http_code["forbidden"]);
            }
            // 验证是否是自己的商家（权限）
            if($coupon->merchant_id != $merchantInfo["id"]){
                throw new ServiceException($this->util->make_message(1,"操作权限不足"),$this->http_code["forbidden"]);
            }
        }
        // 取消门店ID
        if(isset($data["merchant_id"])){
            unset($data["merchant_id"]);
        }
        $data["updated_at"] = date("Y-m-d H:i:s",time());
        // 修改数据
        return  CouponModel::query()->where("id",'=',$id)->update($data);
    }

    /**
     * 删除优惠券
     * @param string $id 优惠券ID
     * @return bool|int
     */
    public function del(string $id): bool|int
    {
        // 获取商户信息
        $merchantInfo = $this->merchantService->info([["user_id",'=',$this->authData["id"]]],['*']);
        if(is_null($merchantInfo)){
            throw new ServiceException($this->util->make_message(1,"请先申请入驻商户"),$this->http_code["no_found"]);
        }
        if($merchantInfo["status"] == 0){
            throw new ServiceException($this->util->make_message(1,"商户已被禁用，请联系平台管理员"),$this->http_code["forbidden"]);
        }
        // 获取优惠券信息
        $coupon = CouponModel::query()->where("id",'=',$id)->first();
        if(is_null($coupon)){
            throw new ServiceException($this->util->make_message(1,"优惠券信息不存在"),$this->http_code["no_found"]);
        }
        // 验证是否是自己的商家（权限）
        if($merchantInfo["id"] != $coupon->merchant_id){
            throw new ServiceException($this->util->make_message(1,"操作权限不足"),$this->http_code["forbidden"]);
        }
        // 验证有没有未使用的有效领取记录，如果有则不允许删除，只能下架
        $result = Db::table("coupon")
            ->join("user_coupon","user_coupon.coupon_id",'=',"coupon.id")
            ->where("coupon.id",'=',$id)
            ->where("user_coupon.period_validity",'=',0)
            ->Where([["user_coupon.is_use",'=',0],["user_coupon.period_validity",'=',1],["user_coupon.expiration_date",">=",date("Y-m-d H:i:s",time())]])
            ->select("user_coupon.*")
            ->first();
        if(! is_null($result)){
            throw new ServiceException($this->util->make_message(1,"现有已领取未使用的有效优惠券，不能删除该优惠券，但您可先下架该优惠券"),$this->http_code["forbidden"]);
        }
        return  CouponModel::where("id",'=',$id)->delete();
    }

    /**
     * 切换优惠券状态，上/下架
     * @param string $id 优惠券ID
     * @return array
     */
    public function check_status(string $id): array
    {
        // 获取商户信息
        $merchantInfo = $this->merchantService->info([["user_id",'=',$this->authData["id"]]],['*']);
        if(is_null($merchantInfo)){
            throw new ServiceException($this->util->make_message(1,"请先申请入驻商户"),$this->http_code["no_found"]);
        }
        if($merchantInfo["status"] == 0){
            throw new ServiceException($this->util->make_message(1,"商户已被禁用，请联系平台管理员"),$this->http_code["forbidden"]);
        }
        // 获取优惠券信息
        $coupon = CouponModel::query()->where("id",'=',$id)->first();
        if(is_null($coupon)){
            throw new ServiceException($this->util->make_message(1,"优惠券信息不存在"),$this->http_code["no_found"]);
        }
        // 验证是否是自己的商家（权限）
        if($merchantInfo["id"] != $coupon->merchant_id){
            throw new ServiceException($this->util->make_message(1,"操作权限不足"),$this->http_code["forbidden"]);
        }
        // 处理变更后的优惠券状态
        $status = intval($coupon->status)  == 0 ? 1 : 0;
        $title = $status == 1 ? "上架" : "下架";
        // 修改数据
        $result = CouponModel::query()->where("id",'=',$id)->update(["status" => $status]);
        if($result){
            return ["code" => 1, "result" => ["status" => $status , "title" => $title]];
        }
        return ["code" => 0, "result" => ["status" => $status , "title" => $title]];
    }

    /**
     * 领取优惠券
     * @param string $id 优惠券ID
     * @return bool|int
     */
    public function receive(string $id): bool|int
    {
        // 获取优惠券信息
        $coupon = CouponModel::query()->where("id",'=',$id)->first();
        if(is_null($coupon)){
            throw new ServiceException($this->util->make_message(1,"优惠券信息不存在"),$this->http_code["no_found"]);
        }
        // 验证优惠券状态
        if($coupon->status == 0){
            throw new ServiceException($this->util->make_message(1,"优惠券已下架"),$this->http_code["forbidden"]);
        }
        // 验证是否在有效期
        if($coupon->period_validity == 1 && $coupon->expiration_date < time()){
            throw new ServiceException($this->util->make_message(1,"优惠券已过期"),$this->http_code["forbidden"]);
        }
        // 验证最大领取数量
        $currentReciveCount = UserCouponModel::where("coupon_id",'=',$id)->count();
        if($currentReciveCount >= $coupon->max_number){
            throw new ServiceException($this->util->make_message(1,"优惠券已被领完，以后请多多关注商家发券活动"),$this->http_code["forbidden"]);
        }
        // 验证用户领取的最大数量
        $currentUserReciveCount = UserCouponModel::where("coupon_id",'=',$id)->where("user_id",'=',$this->authData["id"])->count();
        if($currentUserReciveCount >= $coupon->receive_number){
            throw new ServiceException($this->util->make_message(1,"您只能领取{$coupon->receive_number}次，您可以查看其他发券活动"),$this->http_code["forbidden"]);
        }
        // 获取商户信息
        $merchantInfo = $this->merchantService->info([["user_id",'=',$this->authData["id"]]],['*']);
        if(! is_null($merchantInfo)){
            // 验证是否是自己的商家（权限）
            if($merchantInfo["id"] == $coupon->merchant_id){
                throw new ServiceException($this->util->make_message(1,"商家不能领取自家的优惠券"),$this->http_code["forbidden"]);
            }
        }
        // 领券操作
        $userCoupon = new UserCouponModel();
        $userCoupon->id = $this->generate_id();
        $userCoupon->user_id = $this->authData["id"];
        $userCoupon->coupon_id = $id;
        $userCoupon->is_use = 0;
        $userCoupon->period_validity = $coupon->period_validity;
        $userCoupon->expiration_date = $coupon->period_validity == 0 ? 0 : $coupon->expiration_date;
        // 保存领取数据
        return $userCoupon->save();
    }

    /**
     * 获取优惠券详情
     * @param string $id 优惠券ID
     * @param int $is_user 是否是用户 0：商家 1：用户
     * @return array|null
     */
    public function info(string $id, int $is_user): array|null
    {
        // 获取优惠券信息
        $coupon = CouponModel::query()->where("id",'=',$id)->first();
        if(is_null($coupon)){
            throw new ServiceException($this->util->make_message(1,"优惠券信息不存在"),$this->http_code["no_found"]);
        }
        // 验证权限 is_user 0:商家,1:用户
        if($is_user == 0){
            // 获取商户信息
            $merchantInfo = $this->merchantService->info([["user_id",'=',$this->authData["id"]]],['*']);
            if(! is_null($merchantInfo)){
                // 验证是否是自己的商家（权限）
                if($merchantInfo["id"] != $coupon->merchant_id){
                    throw new ServiceException($this->util->make_message(1,"商家不能查看不属于自己的优惠券"),$this->http_code["forbidden"]);
                }
            }
            // 处理过期时间
            if($coupon->period_validity== 1){
                $coupon->expiration_date = date("Y-m-d H:i:s",$coupon->expiration_date);
            }
            // 返回结果
            return $coupon->toArray();
        }
        // 将优惠券信息转为数组
        $couponArr = $coupon->toArray();
        // 判定领取状态
        // 初始化领取数据
        $receiveRemark = [
            "is_receive" => 1,
            "receive_message" => "可领取"
        ];
        $currentReciveCount = UserCouponModel::where("coupon_id",'=',$id)->count();
        if($currentReciveCount >= $couponArr["max_number"]){
            $receiveRemark["is_receive"] = 0;
            $receiveRemark["receive_message"] = "优惠券已被领完，以后请多多关注商家发券活动";
        }else{
            // 验证用户领取的最大数量
            $currentUserReciveCount = UserCouponModel::where("coupon_id",'=',$id)->where("user_id",'=',$this->authData["id"])->count();
            if($currentUserReciveCount >= $couponArr["receive_number"]){
                $receiveRemark["is_receive"] = 0;
                $receiveRemark["receive_message"] = "您只能领取{$couponArr["receive_number"]}次，您可以查看其他发券活动";
            }
        }
        // 验证是否在有效期
        if($coupon->period_validity == 1 && $coupon->expiration_date < time()){
            $receiveRemark["is_receive"] = 0;
            $receiveRemark["receive_message"] = "已过期，不能领取";
        }
        // 验证上下架状态
        if($couponArr["status"] == 0){
            $receiveRemark["is_receive"] = 0;
            $receiveRemark["receive_message"] = "已下架，不能领取";
        }
        // 注销字段
        unset($couponArr["max_number"]);
        unset($couponArr["receive_number"]);
        // 新增描述字段
        $couponArr["receive_remark"] = $receiveRemark;
        // 处理过期时间
        if($couponArr["period_validity"]== 1){
            $couponArr["expiration_date"] = date("Y-m-d H:i:s",$couponArr["expiration_date"]);
        }
        // 验证是否收藏
        $collection = UserCollectionModel::query()->where("user_id",'=',$this->authData["id"])
            ->where("coupon_id",'=',$id)
            ->first();
        $couponArr["is_collection"] = is_null($collection) ? 0 : 1;
        return $couponArr;
    }

    /**
     * 获取优惠券列表
     * @param array $where 查询条件
     * @param array $field 查询字段
     * @param int $page 当前页数
     * @param int $limit 单页数据条数
     * @return array|null
     */
    public function list(array $where, array $field, int $page, int $limit): array|null
    {
        return CouponModel::query()->where($where)->select($field)->forPage($page,$limit)->get();
    }

    /**
     * 收藏/取消收藏优惠券
     * @param string $coupon_id
     * @return array
     */
    public function collection(string $coupon_id): array
    {
        // 获取用户ID
        $user_id = $this->authData["id"];
        // 获取是否有收藏
        $result = UserCollectionModel::query()->where("user_id",'=',$user_id)
            ->where("coupon_id",'=',$coupon_id)
            ->first();
        if(is_null($result)){
            // 未收藏，则执行收藏逻辑
            $data = [
                "id" => $this->generate_id(),
                "user_id" => $user_id,
                "coupon_id" => $coupon_id,
                "created_at" => date("Y-m-d H:i:s",time()),
                "updated_at" => date("Y-m-d H:i:s",time())
            ];
            if(UserCollectionModel::query()->insert($data)){
                return ["code" => true, "status" => 1];
            }
            return ["code" => false, "status" => 0];
        }
        // 已收藏，则执行取消收藏逻辑
        $res = UserCollectionModel::query()->where("user_id",'=',$user_id)
            ->where("coupon_id",'=',$coupon_id)
            ->delete();
        if($res){
            return ["code" => true, "status" => 0];
        }
        return ["code" => false, "status" => 1];
    }

    /**
     * 生成优惠券UUID
     * @return string uuid
     */
    public function generate_id() : string
    {
        $name = "coupon/uuid/".time().mt_rand(10000,99999);
        return $this->managerService->create_uuid(env("UUID_NAMESPACE",''),$name);
    }

}